﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Moq;
using Moq.Protected;

namespace MoqContrib.AutoMock.Tests.AutoMockingContainers
{
    [TestFixture]
    class WhenMockingServices : TestBase
    {
        [Test]
        public void I_will_first_try_the_heap()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService))).Returns(true);
            var expected = new Mock<IService>();
            _heap.SetupGet(x => x[typeof(IService)]).Returns(expected);
            _generator.Setup(x => x.Generate(typeof(IService)));

            var result = _container.Object.Get<IService>();

            _generator.Verify(x => x.Generate(typeof(IService)), Times.Never());
            _heap.Verify(x => x.ContainsType(typeof(IService)));
#if false
            // This guy fails for some reason. I think it's a bug in moq
            _heap.VerifyGet(x => x[typeof(IService)]);
#endif
            _container.Protected().Verify("RegisterInstance", Times.Never(),
                typeof(IService), ItExpr.IsAny<IService>());
        }

        [Test]
        public void If_the_heap_doesnt_have_it_I_will_use_the_generator()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService))).Returns(false);
            _heap.SetupSet(x => x[typeof(IService)] = It.IsAny<Mock<IService>>());
            _generator.Setup(x => x.Generate(typeof(IService))).Returns(new Mock<IService>());

            var result = _container.Object.Get<IService>();

            _generator.Verify(x => x.Generate(typeof(IService)));
            _heap.Verify(x => x.ContainsType(typeof(IService)));
            _heap.VerifySet(x => x[typeof(IService)] = It.IsAny<Mock<IService>>());
            _container.Protected().Verify("RegisterInstance", Times.Once(),
                typeof(IService), ItExpr.IsAny<IService>());
        }

        [Test]
        public void NONGENERIC_I_will_first_try_the_heap()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService))).Returns(true);
            var expected = new Mock<IService>();
            _heap.SetupGet(x => x[typeof(IService)]).Returns(expected);
            _generator.Setup(x => x.Generate(typeof(IService)));

            var result = _container.Object.Get(typeof(IService));

            _generator.Verify(x => x.Generate(typeof(IService)), Times.Never());
            _heap.Verify(x => x.ContainsType(typeof(IService)));

            _container.Protected().Verify("RegisterInstance", Times.Never(),
                typeof(IService), ItExpr.IsAny<IService>());
        }

        [Test]
        public void NONGENERIC_If_the_heap_doesnt_have_it_I_will_use_the_generator()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService))).Returns(false);
            _heap.SetupSet(x => x[typeof(IService)] = It.IsAny<Mock<IService>>());
            _generator.Setup(x => x.Generate(typeof(IService))).Returns(new Mock<IService>());

            var result = _container.Object.Get(typeof(IService));

            _generator.Verify(x => x.Generate(typeof(IService)));
            _heap.Verify(x => x.ContainsType(typeof(IService)));
            _heap.VerifySet(x => x[typeof(IService)] = It.IsAny<Mock<IService>>());
            _container.Protected().Verify("RegisterInstance", Times.Once(),
                typeof(IService), ItExpr.IsAny<IService>());
        }


        [Test]
        public void WITHKEY_I_will_first_try_the_heap()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService), "service")).Returns(true);
            var expected = new Mock<IService>();
            _heap.SetupGet(x => x[typeof(IService), "service"]).Returns(expected);
            _generator.Setup(x => x.Generate(typeof(IService)));

            var result = _container.Object.Get<IService>("service");

            _generator.Verify(x => x.Generate(typeof(IService)), Times.Never());
            _heap.Verify(x => x.ContainsType(typeof(IService), "service"));

            _container.Protected().Verify("RegisterInstance", Times.Never(),
                typeof(IService), "service", ItExpr.IsAny<IService>());
        }

        [Test]
        [Ignore("Moq appears to choke on the SetupSet for the indexer")]
        public void WITHKEY_If_the_heap_doesnt_have_it_I_will_use_the_generator()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService), "service")).Returns(false);
            _heap.SetupSet(x => x[typeof(IService), "service"] = It.IsAny<Mock<IService>>());
            _generator.Setup(x => x.Generate(typeof(IService))).Returns(new Mock<IService>());

            var result = _container.Object.Get<IService>("service");

            _generator.Verify(x => x.Generate(typeof(IService)));
            _heap.Verify(x => x.ContainsType(typeof(IService), "service"));
            _heap.VerifySet(x => x[typeof(IService)] = It.IsAny<Mock<IService>>());
            _container.Protected().Verify("RegisterInstance", Times.Once(),
                typeof(IService), "service", ItExpr.IsAny<IService>());
        }

        [Test]
        public void WITHKEY_NONGENERIC_I_will_first_try_the_heap()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService), "service")).Returns(true);
            var expected = new Mock<IService>();
            _heap.SetupGet(x => x[typeof(IService), "service"]).Returns(expected);
            _generator.Setup(x => x.Generate(typeof(IService)));

            var result = _container.Object.Get(typeof(IService), "service");

            _generator.Verify(x => x.Generate(typeof(IService)), Times.Never());
            _heap.Verify(x => x.ContainsType(typeof(IService), "service"));

            _container.Protected().Verify("RegisterInstance", Times.Never(),
                typeof(IService), "service", ItExpr.IsAny<IService>());
        }

        [Test]
        [Ignore("Moq appears to choke on the SetupSet for the indexer")]
        public void WITHKEY_NONGENERIC_If_the_heap_doesnt_have_it_I_will_use_the_generator()
        {
            _heap.Setup(x => x.ContainsType(typeof(IService), "service")).Returns(false);
            _heap.SetupSet(x => x[typeof(IService), "service"] = It.IsAny<Mock<IService>>());
            _generator.Setup(x => x.Generate(typeof(IService))).Returns(new Mock<IService>());

            var result = _container.Object.Get(typeof(IService), "service");

            _generator.Verify(x => x.Generate(typeof(IService)));
            _heap.Verify(x => x.ContainsType(typeof(IService), "service"));
            _heap.VerifySet(x => x[typeof(IService), "service"] = It.IsAny<Mock<IService>>());
            _container.Protected().Verify("RegisterInstance", Times.Once(),
                typeof(IService), "service", ItExpr.IsAny<IService>());
        }
    }
}
